﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Intorise.API;
using System.Drawing.Imaging;
using Intorise.Framework;
using System.Runtime.InteropServices;

namespace Intorise.Common
{
    public class ImageTools
    {
        private static Security security = new Security();

        private static int pixelColorRedundance = 30;

        /// <summary>
        /// 颜色容差，默认30
        /// </summary>
        public static int PixelColorRedundance
        {
            get { return pixelColorRedundance; }
            set { pixelColorRedundance = value; if (pixelColorRedundance < 0) { pixelColorRedundance = 0; } }
        }

        /// <summary>
        /// 从一张大图片中查找小图片左上角的坐标
        /// </summary>
        /// <param name="bigImage"></param>
        /// <param name="smallImage"></param>
        /// <returns></returns>
        public static Point SearchImage(Bitmap bigImage, Bitmap smallImage, double size)
        {
            return SearchImage(bigImage, smallImage, new Rectangle(0, 0, 0, 0), size);
        }

        /// <summary>
        /// 从一张大图片中查找小图片左上角的坐标
        /// </summary>
        /// <param name="bigImage"></param>
        /// <param name="smallImage"></param>
        /// <returns></returns>
        public static Point SearchImage(Bitmap bigImage, Bitmap smallImage)
        {
            return SearchImage(bigImage, smallImage, new Rectangle(0, 0, 0, 0), 0.75);
        }

        /// <summary>
        /// 从一张大图片中查找小图片左上角的坐标
        /// </summary>
        /// <param name="bigImage">大图片</param>
        /// <param name="smallImage">小图片</param>
        /// <param name="rectangle">查找范围</param>
        /// <returns></returns>
        public static Point SearchImage(Bitmap bigImage, Bitmap smallImage, Rectangle rectangle, double size)
        {
            bool searched = true;

            if (size > 1) { size = 1; }

            if (rectangle.X >= bigImage.Width)
            {
                rectangle.X = 0;
            }
            if (rectangle.Y >= bigImage.Height)
            {
                rectangle.Y = 0;
            }

            if (rectangle.Width + rectangle.X > bigImage.Width || rectangle.Width <= 0)
            {
                rectangle.Width = bigImage.Width - rectangle.X;
            }
            if (rectangle.Height + rectangle.Y > bigImage.Height || rectangle.Height <= 0)
            {
                rectangle.Height = bigImage.Height - rectangle.Y;
            }

            BitmapData srcData = null;
            BitmapData dstData = smallImage.LockBits(new Rectangle(0, 0, smallImage.Width, smallImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            unsafe
            {
                byte* srcPointer, dstPointer;
                int ySize = rectangle.Bottom - smallImage.Height;
                int xSize = rectangle.Right - smallImage.Width;
                int height = smallImage.Height;
                int width = smallImage.Width;
                int maxCount = (int)(height * width * (1-size));

                for (int y = rectangle.Y; y <= ySize; y++)
                {
                    for (int x = rectangle.X; x <= xSize; x++)
                    {
                        searched = true;
                        srcData = bigImage.LockBits(new Rectangle(x, y, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                        srcPointer = (byte*)srcData.Scan0;
                        dstPointer = (byte*)dstData.Scan0;
                        byte tempa = 0, tempb = 0;
                        int count = 0;

                        for (int i = 0; i < height; i++)
                        {
                            for (int j = 0; j < width; j++)
                            {
                                //tempa = (byte)(*srcPointer * 0.114 + *(srcPointer + 1) * 0.587 + *(srcPointer + 2) * 0.299);
                                //tempb = (byte)(*dstPointer * 0.114 + *(dstPointer + 1) * 0.587 + *(dstPointer + 2) * 0.299);

                                tempa = (byte)((*srcPointer+ *(srcPointer + 1) + *(srcPointer + 2))/3);
                                tempb = (byte)((*dstPointer+ *(dstPointer + 1)  + *(dstPointer + 2))/3);

                                if (Math.Abs(tempa - tempb) > pixelColorRedundance)
                                {
                                    count++;
                                }
                                if (count > maxCount)
                                {
                                    searched = false;
                                    i = height;
                                    break;
                                }

                                srcPointer += 3;
                                dstPointer += 3;
                            }
                            srcPointer += srcData.Stride - width * 3;
                            dstPointer += dstData.Stride - width * 3;
                        }
                        bigImage.UnlockBits(srcData);
                        if (searched)
                        {
                            smallImage.UnlockBits(dstData);
                            return new Point(x, y);
                        }
                    }
                }
            }

            smallImage.UnlockBits(dstData);
            return Point.Empty;
        }

        public static Point SearchImage(Bitmap bigImage, Bitmap smallImage, Rectangle rectangle)
        {
            return SearchImage(bigImage, smallImage, rectangle, 50);
        }

        public static int GetPixel(IntPtr windowHandle, int x, int y)
        {
            int pixel = 0;
            IntPtr dc = Windows.GetWindowDC(windowHandle);
            pixel = Windows.GetPixel(dc, x, y);
            Windows.ReleaseDC(windowHandle, dc);
            return pixel;
        }

        public static int GetPixel(Bitmap image, int x, int y)
        {
            return image.GetPixel(x, y).ToArgb();
        }

        public static void Convert2GrayFast(Bitmap bmpobj)
        {
            unsafe
            {
                BitmapData data = bmpobj.LockBits(new Rectangle(0, 0, bmpobj.Width, bmpobj.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                IntPtr startPoint = data.Scan0;
                byte* begin = (byte*)startPoint.ToPointer();
                int height = bmpobj.Height;
                int width = bmpobj.Width;
                byte temp = 0;

                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {
                        temp = (byte)(*begin * 0.114 + *(begin + 1) * 0.587 + *(begin + 2) * 0.299);
                        *begin = temp;
                        *(begin + 1) = temp;
                        *(begin + 2) = temp;
                        begin += 3;
                    }
                    begin += data.Stride - width * 3;
                }

                bmpobj.UnlockBits(data);
            }
        }

        /// <summary>
        /// 根据RGB，计算灰度值
        /// </summary>
        /// <param name="posClr">Color值</param>
        /// <returns>灰度值，整型</returns>
        public static int GetGrayNumColor(System.Drawing.Color posClr)
        {
            return (posClr.R * 19595 + posClr.G * 38469 + posClr.B * 7472) >> 16;
        }

        /// <summary>
        /// 灰度转换,逐点方式
        /// </summary>
        public static void GrayByPixels(Bitmap bmpobj)
        {
            for (int i = 0; i < bmpobj.Height; i++)
            {
                for (int j = 0; j < bmpobj.Width; j++)
                {
                    int tmpValue = GetGrayNumColor(bmpobj.GetPixel(j, i));
                    bmpobj.SetPixel(j, i, Color.FromArgb(tmpValue, tmpValue, tmpValue));
                }
            }
        }

        /// <summary>
        /// 灰度转换,逐行方式
        /// </summary>
        public static void GrayByLine(Bitmap bmpobj)
        {
            Rectangle rec = new Rectangle(0, 0, bmpobj.Width, bmpobj.Height);
            BitmapData bmpData = bmpobj.LockBits(rec, ImageLockMode.ReadWrite, bmpobj.PixelFormat);// PixelFormat.Format32bppPArgb);
            //    bmpData.PixelFormat = PixelFormat.Format24bppRgb;
            IntPtr scan0 = bmpData.Scan0;
            int len = bmpobj.Width * bmpobj.Height;
            int[] pixels = new int[len];
            Marshal.Copy(scan0, pixels, 0, len);

            //对图片进行处理
            int GrayValue = 0;
            for (int i = 0; i < len; i++)
            {
                GrayValue = GetGrayNumColor(Color.FromArgb(pixels[i]));
                pixels[i] = (byte)(Color.FromArgb(GrayValue, GrayValue, GrayValue)).ToArgb();      //Color转byte
            }

            bmpobj.UnlockBits(bmpData);
        }

        /// <summary>
        /// 平均分割图片
        /// </summary>
        /// <param name="RowNum">水平上分割数</param>
        /// <param name="ColNum">垂直上分割数</param>
        /// <returns>分割好的图片数组</returns>
        public static Bitmap[] GetSplitPics(Bitmap bmpobj, int RowNum, int ColNum)
        {
            if (RowNum == 0 || ColNum == 0)
                return null;
            int singW = bmpobj.Width / RowNum;
            int singH = bmpobj.Height / ColNum;
            Bitmap[] PicArray = new Bitmap[RowNum * ColNum];

            Rectangle cloneRect;
            for (int i = 0; i < ColNum; i++)      //找有效区
            {
                for (int j = 0; j < RowNum; j++)
                {
                    cloneRect = new Rectangle(j * singW, i * singH, singW, singH);
                    PicArray[i * RowNum + j] = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);//复制小块图
                }
            }
            return PicArray;
        }
    }
}
